const koa = require('koa');
const fs = require('fs');
const path = require('path');
const compilerSFC = require('@vue/compiler-sfc');
const compilerDom = require('@vue/compiler-dom');

const app = new koa();

// 路由处理
app.use(async (ctx) => {
  const {url, query} = ctx.request;
  if(url == '/') {
    // 处理html 加载
    ctx.type = 'text/html';
    const fileUrl = path.join(__dirname,'/../src/index.html')
    ctx.body = fs.readFileSync(fileUrl, 'utf-8');
  } else if (url.endsWith('.js')) {
    // 处理js 加载
    const p = path.join(__dirname,'/../src', url);
    ctx.type = 'application/javascript';
    ctx.body = rewritePath(fs.readFileSync(p, 'utf-8'));
  } else if (url.startsWith('/@modules/')) {
    // 处理node_modules下的模块
    const moduleDir = path.join(__dirname, '/..' ,url.replace('@modules', 'node_modules'));
    let module = require(moduleDir+'/package.json').module;
    const filePath = path.join(moduleDir, module);
    ctx.type = 'application/javascript';
    ctx.body = rewritePath(fs.readFileSync(filePath, 'utf-8'));
  } else if (url.indexOf('.vue') > -1) {
    // 处理vue单文件组件
    const p = path.join(__dirname,'/../src', url.split('?')[0]);
    // 获取ast
    const ret = compilerSFC.parse(fs.readFileSync(p, 'utf-8'));
    if (!query.type) {
      const scriptContent = ret.descriptor.script.content;
      const script = scriptContent.replace('export default ', 'const _script = ');
      ctx.type = 'application/javascript';
      ctx.body = `
        ${rewritePath(script)}
        import {render as _render} from '${url}?type=template';
        import '${url}?type=style';
        _script.render = _render;
        export default _script;
      `;
    } else if (query.type === 'template' ) {
      const tpl = ret.descriptor.template.content;
      const render = compilerDom.compile(tpl, {mode:'module'}).code;
      ctx.type = 'application/javascript';
      ctx.body = rewritePath(render);
    } else if (query.type === 'style') {
      const styles = ret.descriptor.styles;
      const styleContent = styles.reduce((pre, cur) => {
        return `${pre}${cur.content.replace(/\n/g, '')}`
      }, '');
      ctx.type = 'application/javascript';
      ctx.body = `
        const _style = document.createElement('style');
        _style.innerText = '${styleContent}'
        document.head.appendChild(_style);
      `;
    }
  }
});

// 裸模块地址重写
function rewritePath(content) {
  return content.replace(/ from ['"](.*)['"]/g, function(s1,s2) {
    if (s2.startsWith("/") || s2.startsWith("./") || s2.startsWith("../")) {
      return s1;
    } else {
      return ` from "/@modules/${s2}"`;
    }
  });
}

app.listen('3000', () => {
  console.log('server is starting at 3000 port')
})

